package JDBC;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author Zhang Chao
 * @Date 2021/6/8 19:42
 * @Version 1.0
 */
public class JDBCTestDriver {
    public static void main(String[] args) {
        // 原生jdbc连接数据库
        testJDBC();
    }

    /**
     * java原生连接jdbc
     * 注意:
     * 1、java 的 jdbc连接的工具类都来自于 java.sql包，不要引错包
     * 2、数据库操作过程中的集合，比如resultset的下标是从1开始的
     */
    public static void testJDBC() {
        // 0 准备工作 在项目目录下新建一个lib目录，考入mysql驱动包，设置jar项目引用
        // 【1 注册数据驱动】
        // 数据库jdbc连接属性信息
        // uri mysql5和mysql8 连接串不一样，8要求有时区属性
        // localhost - 数据库服务器主机名，或者ip地址， 127.0.0.1 表示本机
        // 注意： 如果连接串解析失败，要注意可能是因为 & 引起的，因为有时需要 使用 & 的html转移符号  &amp;
        String strUri5 = "jdbc:mysql://localhost:3306/a-nuc-sx?useUnicode=true&characterEncoding=utf8";
        String strUri8 = "jdbc:mysql://localhost:3306/a-nuc-sx?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong&allowPublicKeyRetrieval=true";
        // drivername的名字 mysql5和mysql8 不一样
        String strDriverName5 = "com.mysql.jdbc.Driver";
        String strDriverName8 = "com.mysql.cj.jdbc.Driver";

        String strUserName = "root";
        String strUserPsw = "root";

        // 注册驱动
//        try {
//            Class.forName(strDriverName8);
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }

        try {
            // 2 获取数据库连接对象
            Connection connection = DriverManager.getConnection(strUri5, strUserName, strUserPsw);
            // 3 获取查询器
            Statement statement = connection.createStatement();
            // 4 准备sql语句
            String strSql = "SELECT * FROM userinfo";
            // 5 获取查询结果集
            ResultSet resultSet = statement.executeQuery(strSql);
            // 6 遍历结果集，进行业务逻辑处理
            // 可以使用迭代的方式进行遍历
            if (resultSet != null) {
                while (resultSet.next()) {
                    //使用getxxx方法获取指定名字或者下标的字段值
                    System.out.println(" 姓名：" + resultSet.getObject("userName") +
                            "; 电话：" + resultSet.getObject(5));
                }
            }

            // TODO 查询完之后，需要将ResultSet中的结果数据，转储到一个集合数据结构中【List+Map】，
            //  然后关闭数据库资源，进行资源回收，减轻数据库服务器的压力； 写一个公用的方法完成这个业务处理；
            /*
              思路提示：
                 在resultset结果集中通过 ResultSetMetaData getMetaData()  方法可以获取，查询结果集中于列信息相关的数据，可以获取 列数；
                 可通过列数的下表获取列表，然可以通过列名从 resultset结果集中获取对应列的值，然后，以列明为key ，以列值为value，存入 map中；
                 然后map存入 list中，这样就完成了查询结果集 resultset的转储业务处理；
             */

            // 业务需要再一次遍历查询结果集的数据
            // 可以使用迭代的方式进行遍历
            // 因为resulstset结果集中使用的是 游标 进行查询结果的遍历 游标只能从前往后移动，到末尾结束
            // 如果再次遍历的话，需要将游标重置到开始位置
            resultSet.beforeFirst();
            System.out.println("将数据库中的数据转储到List+Map的结果集：");
            // 转储的数据结果集
            List<Map<String,Object>> lstRusultSet = new ArrayList<>();

            if (resultSet != null) {
                // 获取查询结果集【列信息】
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                // 获取当前结果集中的【列数】
                int columnCount = resultSetMetaData.getColumnCount();
                while (resultSet.next()) {
                    // 保存当前行数据的Map对象，因为【需要有序】，所以使用 【LinkedHashMap】 实现类
                    Map<String,Object> map = new LinkedHashMap<>();

                    // 通过列数for循环获取每一列的名字，通过获取的列名，获取对应的列值
                    for(int i = 1;i<= columnCount;i++){
                        // 获取对应下标的列名
                        String strColumnName = resultSetMetaData.getColumnName(i);
                        // 通过列名获取对应的列值
                        Object objColumnValue = resultSet.getObject(strColumnName);
                        // 把列名-列值 键值对存入map中
                        map.put(strColumnName, objColumnValue);
                    }

                    // 把保存每一行数据的map存入list中，一个map表示一行数据
                    lstRusultSet.add(map);

                    //使用getxxx方法获取指定名字或者下标的字段值
                    System.out.println(" 姓名：" + resultSet.getObject("userName") +
                            "; 电话：" + resultSet.getObject(5));
                }
            }

            // 测试转储结果
            System.out.println("转储结果：");
            System.out.println(lstRusultSet);

            // 回收资源
            resultSet.close();

            // 如果再次遍历的话，需要将游标重置到开始位置
//            resultSet.beforeFirst();
//            System.out.println("关闭查询器之后，再次遍历查询结果集中的数据：");
//            if (resultSet != null) {
//                while (resultSet.next()) {
//                    //使用getxxx方法获取指定名字或者下标的字段值
//                    System.out.println(" 姓名：" + resultSet.getObject("userName") +
//                            "; 电话：" + resultSet.getObject(5));
//                }
//            }

            System.out.println("关闭查询器之后，再次遍历查询结果集中的数据【转储之后】：");
            System.out.println(lstRusultSet);

            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 也可以在这里回收资源
        }
    }
}
